package jtacck.labmedicine;

import java.util.List;

import android.app.Dialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.Uri;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.MyLocationOverlay;
import com.google.android.maps.Overlay;

/**
 * Extended class of Map Activity that also implements a location listener
 * within itself. Used to display the map and help draw various overlays
 * 
 * @see com.google.android.maps.MapActivity
 * @see android.location.LocationListener
 * 
 * @author Andrew
 * 
 */
public class GoogleMapActivity extends MapActivity implements LocationListener {

    /**
     * Tag used for debugging.
     */
    private static final String TAG = "GoogleMapActivity";

    /**
     * The LocationManager used to retrieve the location properties.
     */
    LocationManager locationManager;

    /**
     * Geocoder used to translate between points and addresses.
     */
    Geocoder geocoder;

    /**
     * Used to display information on the map
     */
    TextView locationText;

    /**
     * The MapView used to display the map.
     */
    MapView mapView;

    /**
     * Stores the controller used to obtain controls of the map.
     */
    MapController mapController;

    /**
     * List of overlays to be drawn
     */
    List<Overlay> mapOverlays;

    /**
     * Icon to be drawn on the points
     */
    Drawable drawable;

    /**
     * The actual class that draws the overlays
     */
    GoogleMapOverlay itemizedoverlay;

    /**
     * Overlay class used to display information about our location.
     */
    MyLocationOverlay myLocOverlay;

    /*
     * (non-Javadoc)
     * 
     * @see com.google.android.maps.MapActivity#onCreate(android.os.Bundle)
     * 
     * Sets up everything we need for this activity. For more information read
     * the comments along the code for this method.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.g_map);

        Button route = (Button) findViewById(R.id.firstButtonId);
        Button findMyself = (Button) findViewById(R.id.secondButtonId);

        route.setOnClickListener(new OnClickListener() {

            /*
             * (non-Javadoc)
             * 
             * @see android.view.View.OnClickListener#onClick(android.view.View)
             * 
             * When the user clicks on the button we want them to be sent to the
             * Google maps and have the route calculated if possible.
             */
            @Override
            public void onClick(View v) {
                if (myLocOverlay.getMyLocation() != null
                        && RouteListActivity.currentHospital != null) {

                    // Create a new intent and pass the URL so that it can be
                    // used to calculate the route
                    Intent intent = new Intent(Intent.ACTION_VIEW, Uri
                            .parse("http://maps.google.com/maps?saddr="
                                    + myLocOverlay.getLastFix().getLatitude()
                                    + ","
                                    + myLocOverlay.getLastFix().getLongitude()
                                    + "&daddr="
                                    + RouteListActivity.currentHospital));

                    // Set the intent to open the package and class for map
                    intent.setComponent(new ComponentName(
                            "com.google.android.apps.maps",
                            "com.google.android.maps.MapsActivity"));

                    startActivity(intent);

                } else {

                    // We don't have a location yet so let user know it
                    Toast.makeText(
                            GoogleMapActivity.this,
                            "Please wait, your location has not been identified",
                            Toast.LENGTH_SHORT).show();
                }
            }
        });

        findMyself.setOnClickListener(new OnClickListener() {

            /*
             * (non-Javadoc)
             * 
             * @see android.view.View.OnClickListener#onClick(android.view.View)
             * 
             * Simply move the map to center on our current location.
             */
            @Override
            public void onClick(View v) {
                if (myLocOverlay.getMyLocation() != null) {
                    mapController.animateTo(myLocOverlay.getMyLocation());
                } else {

                    // We don't have a location yet so let user know it
                    Toast.makeText(
                            GoogleMapActivity.this,
                            "Please wait, your location has not been identified",
                            Toast.LENGTH_SHORT).show();
                }
            }
        });

        locationText = (TextView) this.findViewById(R.id.lblLocationInfo);

        // Retrieves the map and set options
        mapView = (MapView) findViewById(R.id.mapview);
        mapView.setBuiltInZoomControls(true);
        mapView.preLoad();

        // Retrieve the map controller and set the zoom level
        mapController = mapView.getController();
        mapController.setZoom(16);

        geocoder = new Geocoder(this);

        // Get location services
        locationManager = (LocationManager) this
                .getSystemService(Context.LOCATION_SERVICE);

        // Overlays to be used, picture to be drawn, and draws the overlay
        mapOverlays = mapView.getOverlays();
        drawable = this.getResources().getDrawable(R.drawable.icon);
        itemizedoverlay = new GoogleMapOverlay(drawable, this);
        myLocOverlay = new MyLocationOverlay(this, mapView);

    }

    /*
     * (non-Javadoc)
     * 
     * @see com.google.android.maps.MapActivity#onResume()
     * 
     * Begin the listener and calculate any new points obtained since the last
     * pause of this activity.
     */
    @Override
    protected void onResume() {

        super.onResume();

        // Request location updates from both network and GPS
        locationManager.requestLocationUpdates(
                LocationManager.NETWORK_PROVIDER, 5000, 10, this);
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
                5000, 10, this);

        // Set up overlay features now
        myLocOverlay.enableCompass();
        if (myLocOverlay.enableMyLocation()) {
            mapOverlays.add(myLocOverlay);
        }

        // When we get location we want to use it
        myLocOverlay.runOnFirstFix(new Runnable() {
            public void run() {
                if (myLocOverlay.isMyLocationEnabled()) {
                    mapController.animateTo(myLocOverlay.getMyLocation());
                }
            }
        });

    }

    /*
     * (non-Javadoc)
     * 
     * @see com.google.android.maps.MapActivity#onPause()
     * 
     * Closes the listener upon leaving the activity and does some cleanup work.
     */
    @Override
    protected void onPause() {
        super.onPause();
        locationManager.removeUpdates(this);

        // turn off the overlay features
        myLocOverlay.disableMyLocation();
        myLocOverlay.disableCompass();

        // clear all overlays
        mapOverlays.clear();
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.google.android.maps.MapActivity#isRouteDisplayed()
     * 
     * Inherited method that must be implemented. Currently we have no use for
     * it so we return false since we are not displaying a route.
     */
    @Override
    protected boolean isRouteDisplayed() {
        return false;
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * android.location.LocationListener#onLocationChanged(android.location.
     * Location)
     * 
     * This is called whenever we get a new location from our location manager.
     * For now we just want it to animate to the point we're at and tell the
     * user we found their location or something along those lines.
     */
    @Override
    public void onLocationChanged(Location location) {

        this.locationText.setText("Location found!");

        // Necessary because geopoints are a factor of 1e6 of normal coords
        int latitude = (int) (location.getLatitude() * 1e6);
        int longitude = (int) (location.getLongitude() * 1e6);

        GeoPoint point = new GeoPoint(latitude, longitude);
        mapController.animateTo(point);

    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * android.location.LocationListener#onProviderDisabled(java.lang.String)
     * 
     * This method must be implemented as it as abstract. Currently we have no
     * use for it, so it is blank, but it must be implemented.
     */
    @Override
    public void onProviderDisabled(String provider) {

    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * android.location.LocationListener#onProviderEnabled(java.lang.String)
     * 
     * This method must be implemented as it as abstract. Currently we have no
     * use for it, so it is blank, but it must be implemented.
     */
    @Override
    public void onProviderEnabled(String provider) {

    }

    /*
     * (non-Javadoc)
     * 
     * @see android.location.LocationListener#onStatusChanged(java.lang.String,
     * int, android.os.Bundle)
     * 
     * This method must be implemented as it as abstract. Currently we have no
     * use for it, so it is blank, but it must be implemented.
     */
    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {

    }

    /*
     * (non-Javadoc)
     * 
     * @see android.app.Activity#onCreateOptionsMenu(android.view.Menu)
     * 
     * Used to inflate the options menu with a certain XML.
     */
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menu, menu);
        return true;
    }

    /*
     * (non-Javadoc)
     * 
     * @see android.app.Activity#onCreateDialog(int)
     * 
     * Creates the dialog for the logout.
     */
    @Override
    protected Dialog onCreateDialog(int id) {
        switch (id) {
        case 1:
            return SharedMethods.logoutAlert(this);
        }
        return null;
    }

    /*
     * (non-Javadoc)
     * 
     * @see android.app.Activity#onOptionsItemSelected(android.view.MenuItem)
     * 
     * Based on the option chosen in the menu will perform one of the options
     * listed below. Android forces you to have at least two menu items, but we
     * hide the other one. Possibly have more which is why we use a case.
     */
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.text:
            showDialog(1);
            break;
        case R.id.icontext:
            break;
        }
        return true;
    }

    /*
     * (non-Javadoc)
     * 
     * @see android.app.Activity#onKeyDown(int, android.view.KeyEvent)
     * 
     * Displays the dialog for the logout if they back key is pressed.
     */
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            showDialog(1);
            return true;
        }
        return false;
    }

}
